/*================================================================
*   File Name：client.c
*   Mail: a1277992967@163.com 
*   blog: http://www.ycst.club/suggest/ 
*   Author：ycst
*   Created Time：2022年08月08日 星期一 18时40分29秒
*   Describe：客户端
*
================================================================*/

#include "../include/client.h"

int main(int argc, char* argv[]){
	
	int op = 1;
	char recv_buf[BUF_SIZE] = {0};
	char send_buf[BUF_SIZE] = {0};
	Datapack *data = NULL;			//仅供宏函数使用，写下就行，可以不管
	Datapack data1;
	
	char bb[100] = {0};
	int parity = 0;

#if 1
	int s_len = sizeof(sock_server);
	
	sock_server.sin_family = AF_INET;
	sock_server.sin_port = htons(PORT);
	sock_server.sin_addr.s_addr = inet_addr("127.0.0.1");

	int server_id = socket(AF_INET, SOCK_DGRAM, 0);
	struct timeval timeout;
	timeout.tv_sec = 10;
	timeout.tv_usec = 0;
	setsockopt(server_id, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
#endif
	
#if 1
/*================================================================
*   Describe：心跳检测，到期子进程如果没有发送消息，关闭客户端
================================================================*/

	int childid = fork();
	if(childid == 0){	
	    printf("我子进程活了！\r\n");
	    while(1){
	        sleep(HEART_TIME);
	        bzero(recv_buf, sizeof(recv_buf));
		    data_init(data1, 1, 1, BIT, "Heart bit");
		    send_to_server(data1);
	    }
	}
#endif
/*================================================================
*   Describe：
*		链接部分
================================================================*/
	Three_Handshakes(server_id);
	printf("---------------------------------------------------------\r\n");
	
#if 1
	bzero(recv_buf, sizeof(recv_buf));
	data_init(data1, 0, 0, 0, "Nice to meet you\r\n");
	parity = Parity_Create(data1);
	if(parity == 1)	data1.check |= BIP;	
	send_to_server(data1);
	client_error_resend(recv_buf, data1);
#endif
#if 1
	bzero(recv_buf, sizeof(recv_buf));
	recv_from_server(recv_buf);
	client_error_req(recv_buf);
	printf("BIP = %d\r\n", get_check(recv_buf));
	bzero(bb, sizeof(bb));
	get_data(recv_buf, bb);
	printf("服务器发来 ： %s \r\n", bb);

#endif
	printf("---------------------------------------------------------\r\n");
	Four_Waves(server_id);
	return 0;
}

/*================================================================
*   Describe : 三次握手
------------------------------------------------------------------
*	parameter	:
*	@server_id	:	服务器监听描述符	
================================================================*/
int Three_Handshakes(int server_id){
	
	char recv_buf[BUF_SIZE] = {0};	
	char send_buf[BUF_SIZE] = {0};
	Datapack data1;
	int seq1 = 0, ack1 = 0, check1 = 0;
	int seq2 = 0, ack2 = 0, check2 = 0;
	int seq3 = 0, ack3 = 0, check3 = 0;
	int s_len = sizeof(sock_server);
	char buf[100] = "";		//Verify message
	int parity = 0;
	
/*================================================================
*   Describe：
*		第一次客户端发起握手	SYN = 1; seq = x;
================================================================*/
	printf("客户端：开始三次握手!\r\n");
	seq1 = rand() % 100 + 1;
	check1 |= SYN;
	bzero(buf, sizeof(buf));
	strcpy(buf, "VMS1");
	
	data_init(data1, seq1, ack1, check1, buf);
	BP(data1);
	send_to_server(data1);
	client_error_resend(recv_buf, data1);
	printf("客户端：第一次握手成功!\r\n");
	
	printf("seq1 : %d\r\n", seq1);
	printf("ack1 : %d\r\n", ack1);
	printf("check1 : %d\r\n", check1);
	printf("my_data1 : %s\r\n", buf);
	
/*================================================================
*   Describe：
*		第二次次客户端接受握手	SYN = 1; ACK = 1; seq = y; ack = x + 1
================================================================*/
	recv_from_server(recv_buf);
	client_error_req(recv_buf);
	
	seq2 = get_seq(recv_buf);
	ack2 = get_ack(recv_buf);
	check2 = get_check(recv_buf);
	bzero(buf, sizeof(buf));
	get_data(recv_buf, buf);
	
	if(seq2 != 0 && ack2 == seq1 + 1 && (check2 & (SYN | ACK)) > 0 && strcmp(buf, "VMS2") == 0){
		printf("客户端：第二次握手成功!\r\n");
	}
	else{
		printf("客户端：第二次握手失败!\r\n");
		
		printf("seq2 : %d\r\n", seq2);
		printf("ack2 : %d\r\n", ack2);
		printf("check2 : %d\r\n", check2);
		printf("my_data2 : %s\r\n", buf);
		return -1;
	}
	printf("seq2 : %d\r\n", seq2);
	printf("ack2 : %d\r\n", ack2);
	printf("check2 : %d\r\n", check2);
	printf("my_data2 : %s\r\n", buf);
	
/*================================================================
*   Describe：
*		第三客户端发起握手	ACK = 1; seq = x + 1; ack = y + 1
================================================================*/

	seq3 = seq1 + 1;
	ack3 = seq2 + 1;
	check3 |= ACK;
	bzero(buf, sizeof(buf));
	strcpy(buf, "VMS3");
	data_init(data1, seq3, ack3, check3, buf);
	BP(data1);
	send_to_server(data1);
	client_error_resend(recv_buf, data1);
	printf("客户端：第三次握手成功!\r\n");
	printf("seq2 : %d\r\n", seq3);
	printf("ack2 : %d\r\n", ack3);
	printf("check2 : %d\r\n", check3);
	printf("my_data2 : %s\r\n", buf);
}

/*================================================================
*   Describe : 四次挥手
------------------------------------------------------------------
*	parameter	:
*	@server_id	:	服务器监听描述符	
================================================================*/
int Four_Waves(int server_id){
	char recv_buf[BUF_SIZE] = {0};	
	char send_buf[BUF_SIZE] = {0};
	Datapack data1;
	int res = 0;
	int parity = 0;
	int seq1 = 0, ack1 = 0, check1 = 0;
	int seq2 = 0, ack2 = 0, check2 = 0;
	int seq3 = 0, ack3 = 0, check3 = 0;
	int seq4 = 0, ack4 = 0, check4 = 0;
	int s_len = sizeof(sock_server);
	char buf[100] = "";		//Verify message
	
	
/*================================================================
*   Describe：
*		第一次客户端发起挥手	FIN = 1; seq = u;
================================================================*/
	printf("客户端：开始四次挥手!\r\n");
	seq1 = rand() % 100 + 1;
	check1 |= FIN;
	bzero(buf, sizeof(buf));
	strcpy(buf, "VMS1");
	
	data_init(data1, seq1, ack1, check1, buf);
	BP(data1);

	send_to_server(data1);
	client_error_resend(recv_buf, data1);
	printf("客户端：第一次挥手成功!\r\n");
	
	printf("seq1 : %d\r\n", seq1);
	printf("ack1 : %d\r\n", ack1);
	printf("check1 : %d\r\n", check1);
	printf("my_data1 : %s\r\n", buf);
/*================================================================
*   Describe：
*		第二次客户端接受挥手	ACK = 1; seq = v; ack = u + 1
================================================================*/
	recv_from_server(recv_buf);
	client_error_req(recv_buf);
	
	seq2 = get_seq(recv_buf);
	ack2 = get_ack(recv_buf);
	check2 = get_check(recv_buf);
	bzero(buf, sizeof(buf));
	get_data(recv_buf, buf);
	
	if(seq2 != 0 && ack2 == seq1 + 1 && (check2 & ACK) > 0 && strcmp(buf, "VMS2") == 0){
		printf("客户端：第二次挥手成功!\r\n");
	}
	else{
		printf("客户端：第二次挥手失败!\r\n");
		
		printf("seq2 : %d\r\n", seq2);
		printf("ack2 : %d\r\n", ack2);
		printf("check2 : %d\r\n", check2);
		printf("my_data2 : %s\r\n", buf);
		return -1;
	}
	printf("seq2 : %d\r\n", seq2);
	printf("ack2 : %d\r\n", ack2);
	printf("check2 : %d\r\n", check2);
	printf("my_data2 : %s\r\n", buf);
/*================================================================
*   Describe：
*		第三次客户端接受挥手	FIN = 1; ACK = 1; seq = w; ack = u + 1
================================================================*/
	recv_from_server(recv_buf);
	client_error_req(recv_buf);
	seq3 = get_seq(recv_buf);
	ack3 = get_ack(recv_buf);
	check3 = get_check(recv_buf);
	bzero(buf, sizeof(buf));
	get_data(recv_buf, buf);
	
	if(seq3 != 0 && ack3 == seq1 + 1 && (check3 & (FIN | ACK)) > 0 && strcmp(buf, "VMS3") == 0){
		printf("客户端：第三次挥手成功!\r\n");
	}
	else{
		printf("客户端：第三次挥手失败!\r\n");
		
		printf("seq3 : %d\r\n", seq3);
		printf("ack3 : %d\r\n", ack3);
		printf("check3 : %d\r\n", check3);
		printf("my_data3 : %s\r\n", buf);
		return -1;
	}
	printf("seq3 : %d\r\n", seq3);
	printf("ack3 : %d\r\n", ack3);
	printf("check3 : %d\r\n", check3);
	printf("my_data3 : %s\r\n", buf);
/*================================================================
*   Describe：
*		第四次客户端发起挥手	ACK = 1; seq = u + 1; ack = w + 1
================================================================*/
	seq4 = seq1 + 1;
	ack4 = seq3 + 1;
	check4 |= ACK;
	bzero(buf, sizeof(buf));
	bzero(&data1, sizeof(data1));
	strcpy(buf, "VMS4");
	
	data_init(data1, seq4, ack4, check4, buf);
	BP(data1);

	send_to_server(data1);
	client_error_resend(recv_buf, data1);
	

	
	while(1){
		alarm(2 * MSL);
		res = recv_from_server(recv_buf);
		if(res <= 0){
		    alarm(0);
			printf("客户端：第四次挥手成功!\r\n");
	
			printf("seq4 : %d\r\n", seq4);
			printf("ack4 : %d\r\n", ack4);
			printf("check4 : %d\r\n", check4);
			printf("my_data4 : %s\r\n", buf);
			break;
		}
		else{
		    alarm(0);
			printf("客户端：第四次挥手失败!\r\n");
		}
	}
	
}



